from rest_framework.response import Response
from rest_framework import status
from rest_framework_jwt.settings import api_settings
from common.exceptions import JsonAPIException
from utils import aliyuncode, idcard, checkidcard
from common.views.base_views import BaseAPIView, APIView
from random import choice
from tuntun.settings import REGEX_MOBILE, EXPIRE_TIME
from .models import *
from .error_code import ErrCode
from apps.product.models import *
from apps.order.models import *
from apps.repo.models import *
from apps.mix.dbviews import ViewUserProduct
from apps.mix.tasks import *
import json
import re
from common.exceptions import ObjectNotFoundAPIException
from apps.message.models import *
from apps.mix.models import TaskProcess
import time
from tuntun.settings import ALIYUN_SDK
from apps.user.models import UserToken
from .utils import sms_send, create_address
from django.db import transaction
from django.db.models import F
from apps.message.models import UserHistoryMessage, Message, UserTransferHistory
from apps.message.views import CreateMessageView
from apps.mix import tasks
from django.contrib.auth.hashers import make_password, check_password
from django.http import HttpResponse


def check(mobile, auth_code, is_code):
    """
    校验手机号码格式和验证码
    :param mobile:
    :param auth_code: 验证码
    :param is_code: true 验证验证码 false 验证手机号
    :return:
    """
    # 校验手机号
    if not re.match(REGEX_MOBILE, mobile):
        raise JsonAPIException(ErrCode.MOBILE_ERROR.name, ErrCode.MOBILE_ERROR.value,
                               errors=[], status=400)
    # 检验验证码
    if is_code is True:
        if auth_code:
            last_code = AuthCode.objects.filter(mobile=mobile).order_by("-add_timestamp").first()
            if last_code:
                if last_code.code != auth_code:
                    raise JsonAPIException(ErrCode.SMS_CODE_ERROR.name, ErrCode.SMS_CODE_ERROR.value,
                                           errors=[], status=400)
                # 验证过期时间
                now_time = time.time()
                if now_time > last_code.expire_at:
                    raise JsonAPIException(ErrCode.SMS_CODE_EXPIRED.name, ErrCode.SMS_CODE_EXPIRED.value,
                                           errors=[], status=400)
            else:
                raise JsonAPIException(ErrCode.SMS_CODE_ERROR.name, ErrCode.SMS_CODE_ERROR.value,
                                       errors=[], status=400)
        else:
            raise JsonAPIException(ErrCode.SMS_CODE_ERROR.name, ErrCode.SMS_CODE_ERROR.value,
                                   errors=[], status=400)

    return {"code": "0"}


def new_message(user_id):
    # 新消息
    usermessage = UserUnreadMessage.objects.filter(user_id=user_id).first()
    if usermessage:
        unread_message_ids = usermessage.unread_message_ids
        for type, va in Message.MsgType.get_choices():
            if type in unread_message_ids:
                un_reads = unread_message_ids[type]
                if un_reads:
                    return True
    return False


class RequestSmsAuthCodeView(BaseAPIView):
    """
    短信发送
    """
    permission_classes = ()

    def post(self, request, *args, **kwargs):
        data = request.data
        mobile = str(data["mobile"])
        # 手机号校验
        check(mobile, "", False)

        if mobile != '13200000000':
            code = self.generate_code()
            # code = '9999'

            # 阿里云短信发送
            # params = {"code": code}
            # sign_name = ALIYUN_SDK['SIGN']
            # template_code = ALIYUN_SDK['SMS_TPL_ID']
            # template_param = json.dumps(params)
            # ali_code = aliyuncode.send_sms(mobile, sign_name, template_code, template_param)
            # sms_status = json.loads(ali_code)

            # 测试短信验证码
            # sms_status = {'Message': 'OK', 'RequestId': 'C51DFB87-3D63-40D3-979C-AFB48F1F8319',
            #               'BizId': '902703616860479146^0', 'Code': 'OK'}
            # 测试

            # 鼎信发送短信
            content = sms_send(mobile, code)
            content = json.loads(content.decode())


            if content["return_code"] != "00000":
                raise JsonAPIException(ErrCode.SMS_SEND.name, ErrCode.SMS_SEND.value, errors=[content["return_code"], ])
            else:
                expire_at = time.time() + EXPIRE_TIME
                code_record = AuthCode(code=code, mobile=mobile, expire_at=expire_at)
                code_record.save()
                return Response({'authcode_id': code_record.id})
        else:
            code = '8888'
            expire_at = time.time() + 6 * 30 * 24 * 60 * 60  # 半年有效期
            code_record = AuthCode(code=code, mobile=mobile, expire_at=expire_at)
            code_record.save()
        return Response({'authcode_id': code_record.id, 'authcode': code_record.code})

    def generate_code(self):
        """
        生成四位数字的验证码
        :return:
        """
        seeds = "1234567890"
        random_str = []
        for i in range(4):  # 验证码长度 可设置
            random_str.append(choice(seeds))

        return "".join(random_str)


class LoginView(BaseAPIView):
    """
    用户登陆
    """
    permission_classes = ()

    def post(self, request, *args, **kwargs):
        import time
        data = request.data
        if data:
            mobile = data["mobile"]
            auth_code = data["authcode"]
        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, "参数错误")

        # 手机号、短信验证码 校验
        check(mobile, auth_code, True)

        tun_levels = TunLevel.objects.all().order_by("need_grow_coin")
        is_sign = False
        sign_count = 0
        # 是否新用户
        current_user = User.objects.filter(mobile=mobile).first()
        if current_user:
            sign = Sign.objects.filter(user_id=current_user.id).order_by('-sign_datetime').first()
            if sign:
                is_sign = sign.today_sign
        else:
            tunlevle = tun_levels.first()
            # 新建用户
            # x新增 钱包地址
            address = create_address(28)
            current_user = User.objects.create(mobile=mobile, state="NORMAL", tun_level=tunlevle,
                                               certificate_state=User.CertificateState.UNVERIFIED.name,
                                               nickname=User.get_nickname(), purse_address=address)
            # 新建用户囤级权益
            UserTunLevelRight.objects.create(tun_level=tunlevle, user=current_user)

        tun_list = []
        tun_level = current_user.current_tun_level()
        next_tun_level_distance = tun_level["next_tun_level_distance"]

        for tun in tun_levels:
            is_current = False
            if current_user.tun_level.id == tun.id:
                is_current = True

            tun_list.append({
                "id": tun.id,
                "name": tun.name,
                "need_grow_coin": tun.need_grow_coin,
                "is_current": is_current,
                "level_sort": tun.level_sort
            })

        # token
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = {"uid": current_user.id, 'expire_at': time.time()+365*24*60*60}
        token = jwt_encode_handler(payload)
        # 存入缓存
        UserToken.update_token(current_user.id, token)
        #
        resp = {
            "token": token,
            "tun_levels": tun_list,
            "is_sign": is_sign,
            "sign_count": current_user.sign_count,
            "new_message": new_message(current_user.id),
            "next_tun_level_distance": next_tun_level_distance,
            "unread": UserUnreadMessage.unread_count(current_user.id)
        }
        resp.update(current_user.user_info())
        if current_user:
            current_user.state = "NORMAL"
            current_user.last_login_time = datetime.now()
            current_user.save()
        print(resp)
        return Response(resp)


class IdCardVerifyView(BaseAPIView):

    def post(self, request, *args, **kwargs):
        """
          实名认证
        0	匹配
        5	不匹配
        14	无此身份证号码
        96	交易失败，请稍后重试

        """
        user = request.user

        data = request.data
        real_name = data["real_name"]
        card_no = data["card_no"]

        # 身份证号码格式校验
        check_card = checkidcard.checkIdcard(card_no)
        if check_card != ErrCode.CARD_OK.name:
            raise JsonAPIException(check_card, "身份证号码输入错误")

        # 实名认证
        if user.mobile != '13200000000':
            if user.certificate_state == User.CertificateState.VERIFIED.name:
                raise JsonAPIException(ErrCode.CARD_REPEAT.name, ErrCode.CARD_REPEAT.value)
            # 重复校验
            user_card = User.objects.filter(certificate_no=card_no, real_name=real_name).count()
            if user_card > 0:
                raise JsonAPIException(ErrCode.CARD_HAVE.name, ErrCode.CARD_HAVE.value)

            # val_card = idcard.IdCard(real_name, card_no)
            # code = val_card['resp']['code']
            code = 0
        else:
            if card_no == '360400199003270458' and real_name == '湛瑞祥':
                code = 0
            else:
                raise JsonAPIException(ErrCode.CARD_ERROR.name, msg='实名信息错误')

        # val_card = {"data": {"sex": "男", "address": "山东省-潍坊市-寒亭区", "birthday": "1981-11-30"},"resp": {"code": 0, "desc": "匹配"}}
        # {"card_no":"350301198906180060","real_name":"黄瑞冬"}
        # {'data': {'sex': '女', 'address': '福建省-莆田市-市辖区', 'birthday': '1989-06-18'}, 'resp': {'code': 0, 'desc': '匹配'}}

        if code == 0:
            user.real_name = real_name
            user.certificate_no = card_no
            user.certificate_state = User.CertificateState.VERIFIED.name
            user.update_timestamp = time.time()
            user.save()
            return Response({
                "code": ErrCode.RETURN_OK.name,
                "msg": "实名认证成功",

            }, status=status.HTTP_200_OK)
        elif code == 5:
            raise JsonAPIException(ErrCode.CARD_VERIFY_ERROR.name, "信息不匹配")
        elif code == 14:
            raise JsonAPIException(ErrCode.CARD_VERIFY_ERROR.name, "无此身份证号码")
        else:
            raise JsonAPIException(ErrCode.CARD_VERIFY_ERROR.name, "验证失败，请校验信息准确性")


class ChangeBindMobile(BaseAPIView):
    """
    手机号更改
    """

    def post(self, request, *args, **kwargs):
        resp = {}
        data = request.data
        user = request.user
        if data:
            mobile = data["mobile"]
            auth_code = data["authcode"]
            new_mobile = data["new_mobile"]
        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)

        # 旧手机号码验证
        if mobile != "":
            # 手机号、短信验证码 校验
            check(mobile, auth_code, True)
            return Response({"code": ErrCode.RETURN_OK.name, "msg": "验证通过"})

        elif new_mobile != "":  # 验证新手机号
            check(new_mobile, auth_code, True)
            user_info = User.objects.filter(mobile=new_mobile).first()
            if user_info:
                raise JsonAPIException(ErrCode.MOBILE_HAVE.name, ErrCode.MOBILE_HAVE.value)
            user_change = User.objects.filter(id=user.id).first()
            if user_change:
                user_change.mobile = new_mobile
                user_change.update_timestamp = time.time()
                user_change.save()
                return Response({"code": ErrCode.RETURN_OK.name, "msg": "新手机号码更换成功"})
            else:
                raise JsonAPIException(ErrCode.USER_NOT_FOUND.name, ErrCode.USER_NOT_FOUND.value)


class GetUserInfoView(BaseAPIView):
    """
   用户信息，查看自己和他人名片
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        uid = kwargs["id"]
        if uid:
            if user.id == uid:
                tun_level = TunLevel.objects.all().order_by("need_grow_coin")
                is_sign = False
                sign = Sign.objects.filter(user_id=user.id).order_by('-sign_datetime')
                sign_count = sign.count()
                if sign_count > 0:
                    is_sign = sign.first().today_sign

                # 新消息
                have_new_message = new_message(user.id)

                tun_list = []
                tun_level = user.current_tun_level()
                next_tun_level_distance = tun_level["next_tun_level_distance"]
                tun_levels = TunLevel.objects.all().order_by("need_grow_coin")
                for tun in tun_levels:
                    is_current = False
                    if user.tun_level.id == tun.id:
                        is_current = True

                    tun_list.append({
                        "id": tun.id,
                        "name": tun.name,
                        "need_grow_coin": tun.need_grow_coin,
                        "is_current": is_current,
                        "level_sort": tun.level_sort
                    })

                resp = {
                    "next_tun_level_distance": next_tun_level_distance,
                    "tun_levels": tun_list,
                    "is_sign": is_sign,
                    "sign_count": sign_count,
                    "new_message": have_new_message,
                    "unread": UserUnreadMessage.unread_count(user.id)
                }
                resp.update(user.user_info())

                return Response(resp)
            else:
                user = User.objects.filter(id=uid).first()
                if not user:
                    raise ObjectNotFoundAPIException(code=ErrCode.USER_NOT_FOUND.name, msg=ErrCode.USER_NOT_FOUND.value)

                # 检查用户TunLevel
                if user.tun_level is None:
                    user.tun_level = TunLevel.objects.filter().order_by('need_grow_coin').first()
                    user.save()

                uum, _ = UserUnreadMessage.objects.get_or_create(user_id=user.id)
                unread_messages_count = sum([len(e) for e in uum.unread_message_ids])

                count, sign = Sign.objects.filter_by_page(offset=-1, limit=-1, id=user.id)
                return Response({
                    "id": user.id,
                    "avatar": user.avatar,
                    "nickname": user.nickname,
                    "unread_messages_count": unread_messages_count,
                    "total_sign_count": count.__str__(),
                    "balance": user.purse_balance.__str__(),
                    "tun_level_name": user.tun_level.name,
                    "next_tun_level_need_grow_icon": user.tun_level.next_tun_level.need_grow_coin if user.tun_level.next_tun_level else 0,
                    "current_tun_level_need_grow_coin": user.tun_level.need_grow_coin.__str__(),
                    "grow_coin": user.grow_coin.__str__(),
                    "sign_count": user.sign_count,
                })
        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)


class GetTunLevelView(BaseAPIView):
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        tun_levels = TunLevel.objects.all().order_by("need_grow_coin")
        resp = {"count": tun_levels.count(), "items": []}
        for tun in tun_levels:
            resp["items"].append({
                "id": tun.id,
                "name": tun.name,
                "need_grow_coin": tun.need_grow_coin,
                "is_current": False,
                "level_sort": tun.level_sort
            })
        return Response(resp)


class GetMyBlocksList(BaseAPIView):
    """
    我的区块列表(满足TA时请求区块列表)
    ===================
    """

    def get(self, request, *args, **kwargs):
        resp = {'count': 0, 'items': []}
        try:
            offset = int(request.GET.get('offset', -1))
            limit = int(request.GET.get('limit', -1))
        except:
            offset = -1
            limit = -1

        repo_id = request.GET.get('repo_id', '')

        gbs = GoodsBlock.objects.filter(owner_user_id=request.user.id, product_id=kwargs.get('id'), market_order=None,
                                               trade_type__in=(GoodsBlock.TradeType.PRE_SALE.name, GoodsBlock.TradeType.MARKET.name,))

        if repo_id:
            gbs = gbs.filter(repo_id=repo_id)

        count, objs = self.process_page(gbs, offset, limit)

        for gb in objs:
            resp['items'].append(gb.get_block_detail())
        resp['count'] = count
        return Response(resp)


class GetUserProductsListView(BaseAPIView):
    """
    藏茶的产品列表
    ==========

    GET     /user/:id/products

    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        user = request.user
        user_id = kwargs["id"]
        resp = {"count": 0, "items": []}
        if user.id == user_id:  # 自己的
            pass
        else:  # 其他人
            other_user = User.objects.filter(id=user_id).first()
            if not other_user:
                raise JsonAPIException(code=ErrCode.USER_NOT_FOUND.name, msg=ErrCode.USER_NOT_FOUND.value,
                                       errors=[], status=404)
            if not other_user.open_repo:
                return Response(resp)
                # raise JsonAPIException(code=ErrCode.USER_TEA_REPO_UN_PUBLIC.name,
                #                        msg=ErrCode.USER_TEA_REPO_UN_PUBLIC.value,
                #                        errors=[], status=403)

        products = ViewUserProduct.objects.filter(owner_user_id=user_id)
        resp["count"], resp["items"] = products.count(), [p.as_dict() for p in products]
        return Response(resp)


class SignView(BaseAPIView):
    """
    用户签到

    """

    def post(self, request, *args, **kwargs):
        user = User.objects.filter(id=request.user.id).first()
        is_sign = Sign.objects.filter(user_id=user.id).order_by('-sign_datetime').first()
        if is_sign:
            if is_sign.today_sign:
                raise JsonAPIException(ErrCode.SIGN.name, ErrCode.SIGN.value, [])
        with transaction.atomic():
            Sign.objects.create(user_id=user.id, sign_datetime=datetime.now())
            # 签到记录
            sign_count = Sign.objects.filter(user_id=user.id).count()
            # 积分记录
            num = 1
            grow = GrowCoinRecord.objects.filter(user_id=user.id).order_by('-add_timestamp').first()
            if grow:
                num = grow.keep_sign_times + 1

            GrowCoinRecord.objects.create(user_id=user.id,
                                          happen_type=GrowCoinRecord.HappenType.SIGN.name,
                                          amount=GrowCoinRecord.Amount.SIGN.value,
                                          keep_sign_times=GrowCoinRecord.Amount.SIGN.value,
                                          mo_price_multi_n=0
                                          )
            # 修改用户积分
            user.grow_coin += GrowCoinRecord.Amount.SIGN.value

            if num >= 7:
                GrowCoinRecord.objects.create(user_id=user.id,
                                              happen_type=GrowCoinRecord.HappenType.KEEP_SIGN_REWARD.name,
                                              amount=GrowCoinRecord.Amount.KEEP_SIGN_REWARD.value,
                                              keep_sign_times=0,
                                              mo_price_multi_n=0
                                              )
                user.grow_coin += GrowCoinRecord.Amount.KEEP_SIGN_REWARD.value

            user.save()
            tun_level = user.current_tun_level()

            return Response({
                "num": num,
                "sign_count": sign_count,
                "tun_level_name": tun_level["tun_level_name"],
                "grow_coin": user.grow_coin,
                "next_tun_level_distance": tun_level["next_tun_level_distance"]
            })


class UpdateSelfInfoView(BaseAPIView):
    """
    修改用户信息
    昵称 头像
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        data = request.data
        nickname = data["nickname"].strip()
        file_id = data["file_id"]
        print(nickname, file_id)
        if not nickname:
            raise JsonAPIException(code=ErrCode.DATA_ERROR.name, msg='昵称不能为空', status=400)
        if User.objects.filter(~Q(id=user.id), nickname=nickname).count() > 0:
            raise JsonAPIException(ErrCode.NICKNAME_EXIST.name, ErrCode.NICKNAME_EXIST.value, [])

        user = User.objects.filter(id=user.id).first()
        user.nickname = nickname
        if file_id:
            user.avatar_public_file_id = file_id
        user.save()
        return Response({"code": ErrCode.RETURN_OK.name, "nickname": nickname})


class GetBlocksListView(BaseAPIView):
    """
    我的区块列表(满足TA时请求区块列表)
===================

    GET     /user/proucts/:id/blocks

URL参数
-----

    id:
        产品ID

Response
--------

    {
        "count":    2,
        "items":    [
            {
               "id": "block-id",
                "unique_code": "唯一码",
                "repo_id":"仓id",
                "repo_name":"仓名称",
            },
            {
                "id": "block-id",
                "unique_code": "唯一码",
                "repo_id":"仓id",
                "repo_name":"仓名称",
            }
        ]
    }
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        product_id = kwargs["id"]

        resp = {'count': "0", 'items': [], "repo_items": []}
        goods = GoodsBlock.objects.filter(product_id=product_id, owner_user_id=user.id)
        if goods.count() > 0:
            resp["count"] = goods.count()
            for good in goods:
                resp['items'].append(good.get_block_detail())
        return Response(resp)


class WithdrawVerifyView(BaseAPIView):
    """Withdraw"""

    def post(self, request, *args, **kwargs):
        user = request.user
        authcode = AuthCode.objects.filter(code=request.data.get('authcode', ''), mobile=user.mobile,
                                           pk=request.data.get('authcode_id', '')).first()
        if not authcode:
            raise JsonAPIException(ErrCode.SMS_CODE_ERROR.name, ErrCode.SMS_CODE_ERROR.value, status=400)
        if authcode.expire_at <= time.time():
            raise JsonAPIException(ErrCode.SMS_CODE_EXPIRED.name, ErrCode.SMS_CODE_EXPIRED.value, status=400)
        # 此时不记录提现信息
        return Response({})


class WithdrawLaunchView(BaseAPIView):
    """Withdraw Launch"""

    def post(self, request, *args, **kwargs):
        user = request.user
        amount = Decimal(str(request.data.get('amount')))
        if user.balance < amount:
            raise JsonAPIException(ErrCode.YUE_NOT_ENOUGH.name, ErrCode, status=400)
        if amount == Decimal("0"):
            raise JsonAPIException(ErrCode.WITHDRAW_EMPTY.name, ErrCode, status=400)
        wc = WithdrawCash.objects.create(user=user,
                                         amount=amount,
                                         to_account=request.data.get('to_account'),
                                         account_type=request.data.get('account_type'))
        s = task_withdraw_to_alipay_account(withdraw_cash_id=wc.pk)
        wc = WithdrawCash.objects.get(pk=wc.id)
        if not s:
            raise JsonAPIException(code=ErrCode.WITHDRAW_ERROR.name, msg='提现失败',
                                   errors=[wc.provider_response_data, ])
        u = User.objects.get(pk=request.user.id)
        return Response({'new_balance': u.balance.__str__()})

    def get(self, request, *args, **kwargs):
        import datetime
        user = request.user
        y = datetime.datetime.now().year
        ret = {'items': []}
        for m in [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]:
            item = {'month_display': int_2_2d(m) + '月', 'items': []}
            objs = WithdrawCash.objects.filter(date__year=y, date__month=m, user=user,
                                               state=WithdrawCash.State.FINISHED.name).order_by('-add_timestamp')
            for obj in objs:
                item['items'].append(obj.as_dict())
            ret['items'].append(item)

        return Response(ret)


class UploadGetuiInfoView(BaseAPIView):
    permission_classes = ()

    def post(self, request, *args, **kwargs):
        device_type = request.data.get('device_type')
        device_token = request.data.get('device_token')
        getui_clientid = request.data.get('getui_clientid')

        if not getattr(UserDevice.DeviceType, device_type, None):
            raise JsonAPIException(code=ErrCode.DATA_ERROR.name, msg='设备类型错误', status=400)
        if not (device_token and getui_clientid):
            raise JsonAPIException(code=ErrCode.DATA_ERROR.name, msg='参数不能为空', status=400)

        user_device = UserDevice.objects.filter(device_token=device_token).first()
        if not user_device:
            user_device = UserDevice.objects.create(
                user_id=None,
                device_type=device_type,
                device_token=device_token,
                getui_clientid=getui_clientid,
            )

        if isinstance(request.user, User):
            UserDevice.objects.filter(user_id=request.user.id).update(user_id=None)
            user_device.user_id = request.user.id
            user_device.save()
            res = {"unread": UserUnreadMessage.unread_count(request.user.id)}
        else:
            res = {'unread': 0}
        return Response(res)


class GetUserBalanceRecordView(BaseAPIView):
    """
    获取用户金额流向
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        offset = int(request.GET.get('offset', 0))
        limit = int(request.GET.get('limit', 0))
        count, userbalnces = UserBalanceRecord.objects.filter_by_page(offset, limit, user_id=user.id,
                                                                      order='-add_timestamp')

        itmes = {}
        for userbalnce in userbalnces:
            date_line = userbalnce.get_date_line()
            if date_line in itmes:
                itmes[date_line].append(userbalnce.get_detail())
            else:
                list = []
                list.append(userbalnce.get_detail())
                itmes.update({date_line: list})

        resp = {"count": count, "items": itmes}
        return Response(resp)


class TransferAccountView(BaseAPIView):
    """
    钱包转账
    """
    def post(self, request, *args, **kwargs):
        resp= {}
        user = request.user
        addr = request.data.get('address')
        num = request.data.get('num')
        purse_password = request.data.get('password')
        other_user = User.objects.filter(purse_address=addr).first()
        if not other_user:
            raise JsonAPIException(code=ErrCode.USER_NOT_FOUND.name, msg=ErrCode.USER_NOT_FOUND.value,
                                   errors=[], status=404)
        user_id = other_user.id
        if user.purse_balance < float(num):
            raise JsonAPIException("BALANCE_NOT_ENOUGH", "余额不足", status=400)

        if user.purse_password != purse_password:
            ret_bool = check_password(purse_password, user.purse_password)
            if ret_bool == False:
                raise JsonAPIException(code=ErrCode.PASSWORD_ERROR.name, msg=ErrCode.PASSWORD_ERROR.value, status=400)
        # 转账
        try:
            with transaction.atomic():
                User.objects.filter(id=user.id).update(purse_balance=F("purse_balance") - num)
                User.objects.filter(id=user_id).update(purse_balance=F("purse_balance") + num)
                # 明细 收到 xx转账
                UserTransferHistory.objects.create(uid=other_user.id, user_id=user.id, address=user.purse_address, nickname=user.nickname,
                                                   account=num, msg_type=UserTransferHistory.MsgType.RECEIVE.name)
                # 明细 转出， 转给xxx
                UserTransferHistory.objects.create(uid=user.id, user_id=other_user.id, address=addr, nickname=other_user.nickname,
                                                   account=num, msg_type=UserTransferHistory.MsgType.TRANSFER.name)
        except Exception as e:
            return Response("出现错误<%s>" % str(e))
        # # 明细 收到xx转账
        # msg = CreateMessageView.message(msg_type=Message.MsgType.RECEIVE.name,
        #                                 oper_user=other_user, message_user_id=user_id)
        # t = tasks.task_send_transmission_msg.delay(user_id=user_id,
        #                                            transmission_msg_data=msg.make_transmission_msg(),
        #                                            message_id=msg.pk, with_push=True)
        # from apps.mix.models import TaskProcess
        # TaskProcess.objects.create(task_callable="task_send_transmission_msg",
        #                            task_name=tasks.task_send_transmission_msg.name, task_id=t.id)
        #
        # # 明细  转出xx
        # msg = CreateMessageView.message(msg_type=Message.MsgType.TRANSFER.name,
        #                                 oper_user=user, message_user_id=user.id)
        # t = tasks.task_send_transmission_msg.delay(user_id=user.id,
        #                                            transmission_msg_data=msg.make_transmission_msg(),
        #                                            message_id=msg.pk, with_push=True)
        # from apps.mix.models import TaskProcess
        # TaskProcess.objects.create(task_callable="task_send_transmission_msg",
        #                            task_name=tasks.task_send_transmission_msg.name, task_id=t.id)

        resp['code'] = "OK"
        resp['msg'] = "Success"
        return Response(resp)


class ShowPursePasswordView(BaseAPIView):

    def get(self, request):
        """
        钱包信息展示
        :param request: id
        :return:
        """
        resp = {}
        user = request.user
        # id = request.Get.get('id')
        id = user.id
        print(id)
        print(id)
        if id:
            user = User.objects.filter(id=id).first()
            if user:
                resp['purse_balance'] = user.purse_balance
                resp['purse_address'] = user.purse_address
            else:
                return JsonAPIException(ErrCode.USER_NOT_FOUND.name, ErrCode.USER_NOT_FOUND.value)
        else:
            return JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)

        resp['code'] = ErrCode.RETURN_OK.name
        if user.purse_password == "":
            resp['pwdIsNone'] = True
        return Response(resp)


class ModifyPursePasswordView(APIView):
    """
    修改钱包密码
    """
    def post(self, request, *args, **kwargs):

        data = request.data
        user = request.user
        if data:
            old_password = data["oldpassword"]
            new_password = data["newpassword"]
            second_password = data["secondpassword"]
        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)
        print(user.purse_password)
        # 旧密码验证
        if old_password != "":
            # 旧密码
            if(old_password != user.purse_password):
                ret = check_password(old_password, user.purse_password)
                if ret == False:
                    raise JsonAPIException(ErrCode.PASSWORD_ERROR.name, ErrCode.PASSWORD_ERROR.value)

        if new_password != "" and second_password != "":  # 验证新密码
            if new_password != second_password:
                raise JsonAPIException(ErrCode.PASSWORD_ERROR.name, "两次密码不一致")
            if len(new_password) < 6 or len(new_password)>20:
                raise JsonAPIException(code="PASSWORD_LENGTH_ERRO", msg="请输入6-20位字母或数字")

        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)
            print(make_password(new_password))
        try:
            User.objects.filter(id=user.id).update(purse_password=make_password(new_password))
        except Exception as e:
            return Response("出现错误<%s>" % str(e))

        resp = {"code": "OK", "msg": "Success"}
        return Response(resp)


class ForgetPursePasswordView(BaseAPIView):
    """
    忘记钱包密码
    """
    def get(self, request, *args, **kwargs):
        user = request.user
        resp = {}
        mobile = request.GET.get('mobile')
        auth_code = request.GET.get('auth_code')

        if mobile:
            if mobile != user.mobile:
                raise JsonAPIException(code=ErrCode.MOBILE_ERROR.name, msg=ErrCode.MOBILE_ERROR.value, status=400)
        else:
            raise JsonAPIException(code=ErrCode.DATA_ERROR.name, msg=ErrCode.DATA_ERROR.value, status=400)
        if auth_code != "":
            check(mobile, auth_code, True)

        resp['code'] = "OK"
        resp['msg'] = "验证通过"
        return Response(resp)

    def post(self, request, *args, **kwargs):
        data = request.data
        user = request.user
        if data:
            new_password = data["newpassword"]
            same_password = data["samepassword"]
        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)

        if new_password == "" or same_password == "":
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)

        if new_password != same_password:
            raise JsonAPIException(code="PASSWORD_NO_SAME", msg="两次密码不一致")

        if len(new_password) < 6 or len(new_password) > 20:
            raise JsonAPIException(code="PASSWORD_LENGTH_ERRO", msg="请输入6-20位字母或数字")

        try:
            User.objects.filter(id=user.id).update(purse_password=make_password(new_password))
        except Exception as e:
            return Response("出现错误<%s>" % str(e))

        resp = {
            "code": "OK",
            "msg": "密码重置成功"
        }
        return Response(resp)


class HistoryShowView(BaseAPIView):
    """转账明细"""
    def get(self, request, *args, **kwargs):
        user = request.user
        offset = int(request.GET.get('offset', 0))
        limit = int(request.GET.get('limit', 0))
        count, history_obj = UserTransferHistory.objects.filter_by_page(offset, limit, uid=user.id, order='-add_timestamp')
        items = []
        for history in history_obj:
            ret = {}
            history = history.as_dict()
            ret['address'] = history['address']
            ret['account'] = history['account']
            ret['nickname'] = history['nickname']
            ret['date'] = history['date']
            ret['avatar'] = history['avatar']
            ret['msg_type'] = history['msg_type']
            items.append(ret)

            # print(history.as_dict())
        resp = {"count": count, "items": items}
        return Response(resp)


class SetPursePasswordView(APIView):
    """
    设置钱包密码
    """
    def post(self, request, *args, **kwargs):

        data = request.data
        user = request.user
        if data:
            new_password = data["newpassword"]
            second_password = data["secondpassword"]
        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)
        print(user.purse_password)

        if new_password != "" and second_password != "":  # 验证新密码
            if new_password != second_password:
                raise JsonAPIException(ErrCode.PASSWORD_ERROR.name, "两次密码不一致")
            if len(new_password) < 6 or len(new_password) > 20:
                raise JsonAPIException(code="PASSWORD_LENGTH_ERRO", msg="请输入6-20位字母或数字")
        else:
            raise JsonAPIException(ErrCode.DATA_ERROR.name, ErrCode.DATA_ERROR.value)
            print(make_password(new_password))

        try:
            User.objects.filter(id=user.id).update(purse_password=make_password(new_password))
        except Exception as e:
            return Response("出现错误<%s>" % str(e))

        resp = {"code": "OK", "msg": "Success"}
        return Response(resp)